#include<string>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

class CCourse;
class CStudent
{
    string name;
    unsigned id;
    vector<CCourse*> cs;
public:
    CStudent(string nm, unsigned sid): name(nm), id(sid)
    {
        cs.clear();
    }
    ~CStudent()
    {
        cs.clear();
    }
    unsigned getId() const
    {
        return id;
    }
    const string& getName() const
    {
        return name;
    }
    void takeCourse(CCourse* c);
    void quitCourse(CCourse* c);
    string printCourses() const;
    int getTotalCredits() const;
};

class CCourse
{
    string name;
    unsigned id;
    int credit;
    vector<CStudent*> stu;
public:
    CCourse(string nm, unsigned cid, int crdt) : name(nm), id(cid), credit(crdt)
    {
        stu.clear();
    }
    ~CCourse()
    {
        stu.clear();
    }
    int getCredit() const
    {
        return credit;
    }
    unsigned getId() const
    {
        return id;
    }
    const string& getName() const
    {
        return name;
    }
    string printStudents() const;
    void take(CStudent* s);
    void quit(CStudent* s);
};

string CCourse::printStudents() const
{
    string stuList = "";
    for(auto it = stu.begin(); it != stu.end(); ++it)
    {
        stuList += (*it) -> getName();
        if ((it+1)!=stu.end())
            stuList += ",";
    }
    return stuList;
}

void CCourse::take(CStudent* s)
{
    auto it = find(stu.begin(), stu.end(), s);
    if(it != stu.end())
        return;
    stu.push_back(s);
}

void CCourse::quit(CStudent* s)
{
    auto it = find(stu.begin(),stu.end(), s);
    if(it != stu.end())
        stu.erase(it);
}

void CStudent::takeCourse(CCourse* c)
{
    auto it = find(cs.begin(), cs.end(), c);

    if(it != cs.end())
        return;

    cs.push_back(c);
    c->take(this);
}

void CStudent::quitCourse(CCourse* c)
{
    auto it = find(cs.begin(), cs.end(), c);

    if(it != cs.end())
    {
        cs.erase(it);
        c->quit(this);
    }
}

int CStudent::getTotalCredits()const
{
    int credits = 0;
    for(auto it = cs.begin(); it != cs.end(); ++it)
        credits += (*it) -> getCredit();

    return credits;
}

string CStudent::printCourses() const
{
    string courseList = "";
    for(auto it = cs.begin(); it != cs.end(); ++it)
    {
        courseList += (*it) -> getName();
        if ((it+1)!=cs.end())
            courseList += ", ";
    }
    return courseList;
}

int main()
{
    CCourse c1("Java", 101, 3);
    CCourse c2("C++", 201, 3);
    CCourse c3("Data Structure", 102, 4);
    CCourse c4("OS", 302, 3);
    CCourse c5("Software Engineering", 301, 4);

    CStudent s1("Li Lin", 118001);
    CStudent s2("Liu Na", 119003);
    CStudent s3("Zhao Mei", 118011);
    CStudent s4("Zhang Wei", 119006);
    CStudent s5("Sun Yang", 118015);
    CStudent s6("Meng Hui", 118023);

    s1.takeCourse(&c1);
    s1.takeCourse(&c3);
    s2.takeCourse(&c4);
    s2.takeCourse(&c5);

    s3.takeCourse(&c1);
    s3.takeCourse(&c2);
    s3.takeCourse(&c3);
    s3.takeCourse(&c4);
    s3.takeCourse(&c5);

    cout<<"Student ";
    cout << s1.getName() << ":" << s1.printCourses() << "," << s1.getTotalCredits()<<endl;

    cout<<"Student ";
    cout << s3.getName() << ":" << s3.printCourses() << "," << s3.getTotalCredits()<<endl;

    cout<<"Course ";
    cout << c1.getName() << ":" << c1.printStudents()<<endl;

    cout<<"Course ";
    cout << c2.getName() << ":" << c2.printStudents()<<endl;

    cout<<"Course ";
    cout << c3.getName() << ":" << c3.printStudents()<<endl;

    cout<<"Course ";
    cout << c4.getName() << ":" << c4.printStudents()<<endl;

    cout<<"Course ";
    cout << c5.getName() << ":" << c5.printStudents()<<endl;

    s3.quitCourse(&c1);
    cout<<"Student ";
    cout << s3.getName() << ":" << s3.printCourses() << s3.getTotalCredits()<<endl;

    cout<<"Course ";
    cout<<c1.getName() << ":" << c1.printStudents()<<endl;

    return 0;
}

